﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using K3R.Data;
using System.Data.SqlClient;
using System.Data;
using K3R.Email;

namespace K3R.Logic {
	public class Newsletter {
		#region Properties
		[DataMember(Name = "id")] public int ID { get; private set; }
		[DataMember(Name = "email")] public string Email { get; private set; }
		[DataMember(Name = "subscribed")] public bool Subscribed { get; private set; }
		public Guid UniqueIdentifier { get; private set; }
		#endregion

		#region Constructors
		public Newsletter() { }
		#endregion

		#region Instance
		public bool Confirm() {
			bool done = Newsletter.ConfirmGuid(UniqueIdentifier);

			if (done)
				Subscribed = true;

			return done;
		}
		#endregion

		#region Static
		public static int Add(string email, bool sendConfirmation) {
			int id = 0;
			using (Connection conn = new Connection("NewsletterAdd")) {
				conn.AddParameter("@Email", email);
				SqlParameter idParam = conn.AddOutputID();

				try {
					conn.ExecuteNonQuery();
					id = idParam.DBValueOrDefault<int>();
				}
				catch (SqlException err) {
					switch (err.Number) {
						case 2627:
							throw new AlreadyExistsException(err);
						default:
							throw err;
					}
				}
			}

			if (sendConfirmation) {
				Newsletter newsletter = Newsletter.Load(id);
				if (newsletter != null)
					EmailMessage.Add(EmailType.Newsletter, newsletter.Email, newsletter.UniqueIdentifier);
			}

			return id;
		}

		public static int Add(string email) {
			return Add(email, true);
		}

		public static Newsletter AddAndReturn(string email, bool sendConfirmation) {
			return Load(Add(email, sendConfirmation));
		}

		public static bool Edit(int id, string email, bool subscribed) {
			bool done = false;
			using (Connection conn = new Connection("NewsletterEdit")) {
				conn.AddParameter("@ID", id);
				conn.AddParameter("@Email", email);
				conn.AddParameter("@Subscribed", subscribed);

				switch (conn.ExecuteNonQuery()) {
					case 1:
						done = true;
						break;
					case 0:
						throw new NotFoundException();
				}
			}
			return done;
		}

		public static bool ConfirmGuid(Guid uniqueIdentifier) {
			bool done = false;
			using (Connection conn = new Connection("NewsletterConfirmGuid")) {
				conn.AddParameter("@GUID", uniqueIdentifier);

				switch (conn.ExecuteNonQuery()) {
					case 1:
						done = true;
						break;
					case 0:
						throw new NotFoundException();
				}
			}
			return done;
		}

		public static bool ConfirmGuid(Guid uniqueIdentifier, out Newsletter newsletter) {
			newsletter = Newsletter.Load(uniqueIdentifier);
			return newsletter.Confirm();
		}

		public static Newsletter Load(int id) {
			Newsletter newsletter = null;
			using (Connection conn = new Connection("NewsletterLoad")) {
				conn.AddParameter("@ID", id);

				SqlDataReader dr = conn.ExecuteReader(CommandBehavior.SingleRow);
				if (dr.Read())
					newsletter = Reader(dr);
				else
					throw new NotFoundException();
			}
			return newsletter;
		}

		public static Newsletter Load(Guid uniqueIdentifier) {
			Newsletter newsletter = null;
			using (Connection conn = new Connection("NewsletterLoad")) {
				conn.AddParameter("@GUID", uniqueIdentifier);

				SqlDataReader dr = conn.ExecuteReader(CommandBehavior.SingleRow);
				if (dr.Read())
					newsletter = Reader(dr);
				else
					throw new NotFoundException();
			}
			return newsletter;
		}

		public static List<Newsletter> List(bool? subscribed) {
			using (Connection conn = new Connection("NewsletterList")) {
				conn.AddParameter("@Subscribed", subscribed);

				return ListReader(conn.ExecuteReader());
			}
		}

		public static Guid LoadGuid(int id) {
			Guid guid = Guid.Empty;
			using (Connection conn = new Connection("NewsletterLoad")) {
				conn.AddParameter("@ID", id); ;

				SqlDataReader dr = conn.ExecuteReader(CommandBehavior.SingleRow);
				if (dr.Read())
					guid = dr["Guid"].DBValueOrDefault<Guid>();
				else
					throw new NotFoundException();
			}
			return guid;
		}
		#endregion

		#region Reader Helpers
		protected static Newsletter Reader(SqlDataReader dr) {
			return new Newsletter {
				ID = dr["id"].DBValueOrDefault<int>(),
				Email = dr["email"].DBValueOrDefault<string>(),
				Subscribed = dr["subscribed"].DBValueOrDefault<bool>(),
				UniqueIdentifier = dr["GUID"].DBValueOrDefault<Guid>()
			};
		}

		protected static List<Newsletter> ListReader(SqlDataReader dr) {
			List<Newsletter> list = new List<Newsletter>();

			while (dr.Read())
				list.Add(Reader(dr));

			return list;
		}
		#endregion
	}
}
